package com.jt.aop;

import com.jt.annotation.CacheFind;
import com.jt.util.ObjectMapperUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisSentinelPool;
import redis.clients.jedis.ShardedJedis;

import java.util.Arrays;

@Aspect
@Component
public class CacheAOP {
    
    @Autowired
    //private Jedis jedis;//redis单台
    //private ShardedJedis jedis;//redis分片机制
    //private JedisSentinelPool sentinelPool;//redis 哨兵
    private JedisCluster jedis;

    /**
     * 实现思路：
     *      1.动态获取key  用户自定义的前缀+用户参数
     *      2.判断key是否存在
     *              存在 true  获取缓存数据之后，将json转化为对象后返回
     *              不存在 false 应该查询数据库，之后将数据保存到redis中，默认30天超时
     * @param joinPoint
     * @return
     */
    @Around("@annotation(cacheFind)")
    public Object around(ProceedingJoinPoint joinPoint, CacheFind cacheFind){
        //Jedis jedis = sentinelPool.getResource();
        Object result=null;
        //1.获取key的前缀
        String key=cacheFind.key();
        //2.获取方法参数
        String args= Arrays.toString(joinPoint.getArgs());
        key=key+"::"+args;
        //System.out.println(key);
        //System.out.println("环绕通知开始");
        try {
            //判断缓存中是否有数据
            if(jedis.exists(key)){
                String json=jedis.get(key);
                //获取返回值类型
                MethodSignature signature = (MethodSignature)joinPoint.getSignature();
                result=ObjectMapperUtil.toObject(json,signature.getReturnType());
                System.out.println("查询缓存");
            }else {
                result=joinPoint.proceed();
                String json = ObjectMapperUtil.toJSON(result);
                //判断数据中是否有超时时间
                if(cacheFind.seconds()>0){
                    jedis.setex(key, cacheFind.seconds(), json);
                }else {
                    jedis.set(key, json);
                }
                System.out.println("调用数据库");
            }

        } catch (Throwable throwable) {
            throwable.printStackTrace();
            throw new RuntimeException(throwable);
        }
        //jedis.close();//关池操作
        return result;
    }


//    @Pointcut("bean(itemCatServiceImpl)")
//    //@Pointcut("within(com.jt.service.*)")
//    //@Pointcut("execution(* com.jt.service..*.add(..))")
//    public void pointCut(){
//
//    }
//
//
//    @Before("pointCut()")
//    public void before(JoinPoint joinPoint){
//        //获取目标对象
//        Object target = joinPoint.getTarget();
//        //获取目标对象路径 包名+类名+方法名
//        String className = joinPoint.getSignature().getDeclaringTypeName();
//        String methodName = joinPoint.getSignature().getName();
//        System.out.println(className+"."+methodName);
//        //获取参数类型
//        System.out.println(joinPoint.getArgs());
//
//    }
//    @Around("pointCut()")
//    public Object around(ProceedingJoinPoint joinPoint){
//
//        Object data =null;
//        try {
//            data = joinPoint.proceed();
//        } catch (Throwable throwable) {
//            throwable.printStackTrace();
//        }
//        return data;
//    }
}
